<?php
declare (strict_types=1);

namespace app\common\model;

use addons\Target\facade\Target;

use think\Exception;
use think\facade\Cache;
use think\facade\Event;

/**
 * @mixin \think\Model
 */
class Relation extends Base
{

    protected $name = 'user_relation';

    public function getAll($param)
    {
        try {

            return $this->where($param)->select()->toArray();

        } catch (\Exception $e) {
            return [];
        }
    }

    protected function user()
    {
        return $this->hasOne(User::class, 'id', 'uid')
            ->field('id,code,nickname,mobile,is_active,my_total,team_total,level_id');
    }

    protected function fresh()
    {
        return $this->hasOne(User::class, 'id', 'new_uid')
            ->field('id,code,photo,nickname,mobile,my_total,team_total,level_id,is_studio,studio_reward');
    }

    public static function generate(int $new_uid, $new_code, int $parentId, string $parentCode): bool
    {
        try {
            parent::create([
                'uid'      => $parentId,
                'code'     => $parentCode,
                'algebra'  => 1,
                'new_uid'  => $new_uid,
                'new_code' => $new_code,
            ]);
            $time = time();

            parent::where('new_uid', $parentId)
                ->field('uid,code,algebra + 1 as algebra,' . $time . ' as create_time,' . $time . ' as update_time,' . $new_uid . ' as new_uid,' . $new_code . ' as new_code')
                ->selectInsert([
                    'uid',
                    'code',
                    'algebra',
                    'create_time',
                    'update_time',
                    'new_uid',
                    'new_code',
                ], (new static())->getName());

            return true;
        } catch (\Exception $e) {
            throw new Exception($e->getMessage());
        }

    }

    /**
     * @param $amount - 金额
     * @param $uid - 会员ID
     * @param string $key - 团队业绩key
     * 原点 2021年12月28日11:50:17 更新团队业绩
     */
    public static function renewTeamTotal($amount, $uid, $key = 'team_total')
    {
        $all_id = parent::where('new_uid', $uid)->column('uid');
        if (!empty($all_id)) {
            User::whereIn('id', $all_id)->inc($key, floatval($amount))->update();
            User::whereIn('id', $all_id)->inc('month_total', floatval($amount))->update();
        }
    }

    //销售提成
    public static function sales_commission($p_uid,$uid)
    {
        $sales_commission = Cache::get('system')['sales_commission'];
        Target::Account()->basics($p_uid, 'reward', $sales_commission, '销售提成', '+')
            ->createBonus($uid, 1);
        if ($sales_commission > 0) {
            Event::trigger('Statistics', ['key' => 'expend', 'value' => $sales_commission]);
        }
    }

    /**
     * @param $uid
     * @param $total
     * @return array|int[]
     * 原点 2023年7月12日14:16:53 团队奖
     */
    public static function teamBonus($uid, $total, $recoil_count): array
    {
        try {

            $list = parent::with('user')->where('new_uid', $uid)
                ->field('id,uid,algebra')->order('algebra', 'asc')->select();
            $poor = 0;
            $level_id = 0;
            $expendTotal = 0;
            $flat = 0;
            $flat_open = true;
            $recoil_tp = Cache::get('system')['recoil_tp'];
            //$flat_total = 0;
            foreach ($list as $item) {
                if ($item->user->is_active != 2 || $item->user->is_out) continue;
                //大区加速
                if ($item->user->recoil_count <= 1 && $recoil_count <= 1) {
                    //大区加速
                    $areaAll = User::where('parent_id', $item->uid)->order('team_total', 'desc')
                        ->column('my_total+team_total as team_total,id');
                    $max_speed = Cache::get('system')['max_speed'];
                    if (!empty($areaAll) && $max_speed > 0 && count($areaAll) > 1) {
                        $max = array_shift($areaAll);
                        $ids = Relation::where(['uid' => $max['id']])->column('new_uid');
                        $ids[] = $max['id'];
                        if (in_array($uid, $ids)) {
                            $amount = UserRelease::testingCapping($item->uid, round($total * $max_speed, 2));
                            $recoil = round($amount * $recoil_tp, 2);
                            Target::Account()->basics($item->uid, ['recoil', 'bonus'], [$recoil, $amount - $recoil], '大市场加速', '+')
                                ->createBonus($uid, 5);
                        }
                    }
                }
                //直推
                if ($item->algebra == 1) {
                    $count = User::where(['is_active' => 2, 'parent_id' => $item->uid])->count();
                    $tp = $count >= 3 ? Cache::get('system')['speed_3'] : Cache::get('system')['speed_' . $count];
                    $amount = UserRelease::testingCapping($item->uid, round($total * $tp, 2));
                    if ($amount > 0) {
                        $expendTotal += $amount;
                        $recoil = round($amount * $recoil_tp, 2);
                        Target::Account()->basics($item->uid, ['recoil', 'bonus'], [$recoil, $amount - $recoil], '消费分润', '+')
                            ->createBonus($uid, 2);
                    }
                }
                //团队奖
                $level = Level::where('id', $item->user->level_id)->find();
                if (empty($level)) continue;
                if ($item->user->level_id > $level_id && $level->tp > $poor) {
                    $amount = UserRelease::testingCapping($item->uid, round($total * ($level->tp - $poor), 2));
                    if ($amount > 0) {
                        $expendTotal += $amount;

                        $recoil = round($amount * $recoil_tp, 2);
                        Target::Account()->basics($item->uid, ['recoil', 'bonus'], [$recoil, $amount - $recoil], '培育分润', '+')
                            ->createBonus($uid, 3);
                    }
                    $poor = $level->tp;
                    $level_id = $item->user->level_id;
                    $flat = $item->user->level_id;
                    $flat_open = true;
                    //$flat_total = $amount;
                } else {

                    if ($item->user->level_id == $flat && $flat_open) {
                        $amount = UserRelease::testingCapping($item->uid, round($total * $level->flat_tp, 2));
                        if ($amount > 0) {

                            $recoil = round($amount * $recoil_tp, 2);
                            Target::Account()->basics($item->uid, ['recoil', 'bonus'], [$recoil, $amount - $recoil], '平级奖', '+')
                                ->createBonus($uid, 4);

                            $expendTotal += $amount;
                        }
                        $flat_open = false;
                    }
                }
            }
            if ($expendTotal > 0) {
                Event::trigger('Statistics', ['key' => 'expend', 'value' => $expendTotal]);
            }
            return ['code' => 1];
        } catch (\Exception $e) {
            return ['code' => -1, 'msg' => $e->getMessage()];
        }
    }

    /**
     * @param $uid
     * @return array
     * 原点 2023年5月12日17:01:26 升级
     */
    public static function upgrade($uid): array
    {
        try {
            $user = User::find($uid);
            $level = Level::where('id', '>', $user->level_id)
                ->where('my_total', '<=', $user->my_total)
                ->order('id', 'desc')
                ->find();
            if ($level) {
                User::update(['level_id' => $level->id, 'id' => $uid]);
                if($level->id==2)
                {
                    $user_assets =  Assets::where(['uid'=>$uid])->find();
                    if($user_assets->freeze)
                    {
                        $freeze = $user_assets->freeze;
                        $user_assets->freeze = 0;
                        $user_assets->reward = $user_assets->reward+$freeze;
                        $user_assets->save();
                        User::where('id', $uid)->inc('income', floatval($freeze))->update();//收入
                    }
                }
            }
            return ['code' => 1, 'msg' => 'success'];
        } catch (\Exception $e) {
            return ['code' => -1, 'msg' => $e->getMessage()];
        }
    }


    //直推间推奖
    public static function direct($uid,$pid,$amount): array
    {
        try {
            $user = User::find($pid);
            $direct = Cache::get('system')['direct'];
            $direct = bcmul((string)$amount,(string)$direct,2);
            if($direct>0)
            {
                if($user->level_id==2)
                {
                    Target::Account()->basics($pid, 'reward', $direct, '直推奖', '+')
                        ->createBonus($uid, 1);
                    User::where('id', $pid)->inc('income', floatval($direct))->update();//收入
                }else{
                    Target::Account()->basics($pid, 'freeze', $direct, '直推奖', '+')
                        ->createBonus($uid, 1);
                }

                Event::trigger('Statistics', ['key' => 'expend', 'value' => $direct]);
            }
            if($user->parent_id)
            {
                $indirect = Cache::get('system')['indirect'];
                $indirect = bcmul((string)$amount,(string)$indirect,2);
                if($indirect>0)
                {
                    $p_user = User::find($user->parent_id);
                    if($p_user->level_id==2)
                    {
                        Target::Account()->basics($user->parent_id, 'reward', $indirect, '间推奖', '+')
                            ->createBonus($uid, 2);
                        User::where('id', $user->parent_id)->inc('income', floatval($indirect))->update();//收入
                    }else{
                        Target::Account()->basics($user->parent_id, 'freeze', $indirect, '间推奖', '+')
                            ->createBonus($uid, 2);
                    }
                    Event::trigger('Statistics', ['key' => 'expend', 'value' => $indirect]);
                }
            }
            return ['code' => 1];
        } catch (\Exception $e) {
            return ['code' => -1, 'msg' => $e->getMessage()];
        }
    }


    //见点奖
    public static function bonus($uid,$amount)
    {
        try {
            $bonus_generation = Cache::get('system')['bonus_generation'];//代数
            $list = parent::with('user')->where('new_uid', $uid)->where('algebra','<=',$bonus_generation)
                ->field('id,uid,algebra')->order('algebra', 'asc')->select();
            if($list)
            {
                $indirect = 0;
                $bonus_proportion = Cache::get('system')['bonus_proportion'];//奖励
                foreach ($list as $k=>$v)
                {
                    $bonus = bcmul((string)$amount,(string)$bonus_proportion,2);
                    if($bonus>0)
                    {
                        if($v->user->level_id==2)
                        {
                            Target::Account()->basics($v->uid, 'reward', $bonus, '见点奖', '+')
                                ->createBonus($uid, 3);
                            User::where('id', $v->uid)->inc('income', floatval($bonus))->update();//收入
                        }else{
                            Target::Account()->basics($v->uid, 'freeze', $bonus, '见点奖', '+')
                                ->createBonus($uid, 3);
                        }
                        $indirect+=$bonus;
                    }
                }
                Event::trigger('Statistics', ['key' => 'expend', 'value' => $indirect]);
            }
            return ['code' => 1];
        } catch (\Exception $e) {
            return ['code' => -1, 'msg' => $e->getMessage()];
        }
    }


    //工作室
    public static function studio()
    {
        try {
            $users = User::where(['is_studio'=>1])->field('id,studio_reward,level_id')->select();
            $income = 0;
            foreach ($users as $k=>$v)
            {
                $list = parent::with('fresh')->where('uid', $v->id)
                    ->field('id,new_uid,algebra')->order('algebra', 'asc')->select();
                $user_list = parent::where('uid', $v->id)
                    ->field('id,new_uid,algebra')->order('algebra', 'asc')->column('new_uid');
                foreach ($list as $key=>$value)
                {
                    if($value->fresh->is_studio)
                    {
                        $new_uids = parent::where('uid', $value->new_uid)
                            ->field('id,new_uid,algebra')->order('algebra', 'asc')->column('new_uid');
//                        $new_uids[] = $value->new_uid;
                        $user_list = array_diff($user_list,$new_uids);
                    }
                }

               $newly_total = User::whereIn('id',$user_list)->sum('newly_total');
               $bonus = bcmul((string)$newly_total,(string)$v->studio_reward,2);
                if($bonus>0)
                {
                    if($v->level_id==2)
                    {
                        Target::Account()->basics($v->id, 'reward', $bonus, '工作室奖励', '+')
                            ->createBonus($v->id, 4);
                    }else{
                        Target::Account()->basics($v->id, 'freeze', $bonus, '工作室奖励', '+')
                            ->createBonus($v->id, 4);
                    }
                    $income+=$bonus;
                }
            }
            Event::trigger('Statistics', ['key' => 'expend', 'value' => $income]);
            return ['code' => 1,'msg'=>'发放成功'];
        } catch (\Exception $e) {
            return ['code' => -1, 'msg' => $e->getMessage()];
        }
    }


    //培育奖
    public static function cultivate()
    {
        try {
            $user_list = User::where(['is_active'=>2,'delete_time'=>0])->select();
            $cultivate = Cache::get('system')['cultivate'];
            $income = 0;
            foreach ($user_list as $k=>$v)
            {
                if($v->parent_id)
                {
                    $p_user = User::find($v->parent_id);
                    $bonus = bcmul((string)$v->income,(string)$cultivate,2);
                    if($bonus>0)
                    {
                        if($p_user->level_id==2)
                        {
                            Target::Account()->basics($v->parent_id, 'reward', $bonus, '培育奖', '+')
                                ->createBonus($v->id, 5);
                        }else{
                            Target::Account()->basics($v->parent_id, 'freeze', $bonus, '培育奖', '+')
                                ->createBonus($v->id, 5);
                        }
                        $income+=$bonus;
                    }
                }
            }
            Event::trigger('Statistics', ['key' => 'expend', 'value' => $income]);
            return ['code' => 1,'msg'=>'发放成功'];
        } catch (\Exception $e) {
            return ['code' => -1, 'msg' => $e->getMessage()];
        }
    }



    public static function Referrer($uid,$p_id){
        parent::startTrans();
        try {

            $p_user = User::where('id',$p_id)->field('id,nickname,code')->find();//推荐人
            User::update(['parent_id'=>$p_user->id,'parent_name'=>$p_user->nickname,'parent_code'=>$p_user->code],['id'=>$uid]);//修改推荐人

            $team_list = parent::where('uid', $uid)->column('new_uid');//获取团队
            $team_list[] = $uid;
            parent::whereIn('new_uid', $team_list)->delete();//删除旧推荐关系

            $user = User::whereIn('id', $team_list)->field('id,code,parent_id,parent_code')->order('id','asc')->select();
            foreach ($user as $k=>$v){
                Relation::generate($v->id, $v->code, $v->parent_id, $v->parent_code);
            }
            parent::commit();
        } catch (\Exception $e) {
            parent::rollback();
            dump($e->getMessage());die;
            return ['code' => -1, 'msg' => $e->getMessage()];
        }
    }



    public static function getPageList($map = [],
                                       $field = '*',
                                       $page = 1,
                                       $limit = 20,
                                       $merge = true,
                                       $with = [],
                                       $in = [],
                                       $sort = [],
                                       $like = [],
                                       $time = [], $withoutField = '', $append = [])
    {
        try {

            $map = $merge ? array_merge($map, ['status' => 1]) : $map;


            $that = !empty($with) ? parent::with($with)->where($map) : parent::where($map);
            if (!empty($like)) {
                $that->whereLike($like['field'], '%' . $like['keyword'] . '%');
            }
            if ($time) {
                foreach ($time as $k => $v) {
                    $times = explode(' - ', $v['value']);
                    $that->whereBetweenTime($v['key'], $times[0], $times[1]);
                }
            }
            if (!empty($in)) {
                foreach ($in as $k => $v) {
                    $that->whereIn($k, $v);
                }
            }
            if ($withoutField) {
                $that->withoutField($withoutField);
            } else {
                $that->field($field);
            }
            $count = $that->count();
            $that->page(intval($page), intval($limit));
            if (!$sort) {
                $that->order($merge ? 'sort' : 'create_time', 'desc');
            } else {
                $that->order($sort['key'], $sort['value']);
            }
            $list = $that->select();
            foreach ($list as $k=>$v)
            {
                $v['one'] = Relation::with('fresh')->where(['uid' =>$v->new_uid, 'algebra' => 1])->select();

                    foreach ($v['one'] as $key=>$value)
                    {
                        $value['two'] = Relation::with('fresh')->where(['uid' => $value->new_uid, 'algebra' => 1])->select();
                    }

            }
//            dump($list);die;
            if ($append) {
                $list->append($append);
            }
            $allPage = intval(ceil($count / $limit));
            return ['code' => 1, 'msg' => 'success', 'data' => $list, 'pages' => $allPage];

        } catch (\Exception $e) {

            return ['code' => $e->getCode(), 'message' => $e->getMessage()];

        }
    }


}
